#include "EasyXMen_sm2_InternalHandle.h"
#include "istd_lib.h"
#include "Crypto.h"
#include "EasyXMen_asn1.h"
#include <time.h>

#define MAX_BUFFER_SIZE (2 + MAX_USERID_LEN + 128 + 64 + 64)
#define MAX_USERID_LEN 256  // 假设 userid 的最大长度为 256 字节
#define MAX_MSG_LEN 4096    // 假设消息的最大长度为 4096 字节
#define MAX_KBUF_SIZE 256  // 假设 kbuf 的最大长度为 256 字节
#define BUF_SIZE (SM3_DIGEST_SIZE * 2 + 4)  // buf 的大小为 68 字节
#define MAX_OUT_LEN (MAX_MSG_LEN + 128)  // 假设输出的最大长度为消息长度 + 128 字节


#define SEED_CONST 0x1BD8C95A
extern Crypto_JobType Crypto_StoredJob;
XMen_FP_EccT Ecc256 = {
    /* Prime modulus p: Defines the finite field over which the curve is defined*/
    "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
    /*Curve coefficient A: One of the coefficients of the equation defining the elliptic curve (y^2 = x^3 + Ax + B)*/
    "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
    /*Curve coefficient B: The other coefficient of the equation defining the elliptic curve.*/
    "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
    /*Order n of the base point G: The number of points that can be generated by repeatedly adding G to itself*/
    "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
    /*X-coordinate of the base point G: A predefined point on the curve used as a generator for public keys*/
    "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
    /*Y-coordinate of the base point G: The corresponding Y value for the generator point's X coordinate*/
    "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0",
};

unsigned char sm2_par_dig[128] = {
    255, 255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
    255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 252,
    40, 233, 250, 158, 157, 159, 94, 52, 77, 90, 158, 75, 207, 101, 9, 167,
    243, 151, 137, 245, 21, 171, 143, 146, 221, 188, 189, 65, 77, 148, 14, 147,
    50, 196, 174, 44, 31, 25, 129, 25, 95, 153, 4, 70, 106, 57, 201, 148,
    143, 227, 11, 191, 242, 102, 11, 225, 113, 90, 69, 137, 51, 76, 116, 199,
    188, 55, 54, 162, 244, 246, 119, 156, 89, 189, 206, 227, 107, 105, 33, 83,
    208, 169, 135, 124, 198, 42, 71, 64, 2, 223, 50, 229, 33, 57, 240, 160};

    static int EasyXMen_SM2_Sig2Der(const uint8 *r, const uint8 *s, uint8 **out, uint32 *outlen)
    {
        uint32_t len = 0;
        int result = 0;
    
        // MISRA C:2012 Rule 1.3: Ensure no side effects in expressions
        if ((r == NULL) || (s == NULL))
        {
            return 0;
        }
    
        // Calculate total length and encode signature components
        result = XMen_lib_asn1_sm2_integer_to_der(r, 32, NULL, &len);
        if (result != 1)
        {
            return -1;
        }
    
        result = XMen_lib_asn1_sm2_integer_to_der(s, 32, NULL, &len);
        if (result != 1)
        {
            return -1;
        }
    
        result = XMen_lib_asn1_sm2_sequence_header_to_der(len, out, outlen);
        if (result != 1)
        {
            return -1;
        }
    
        result = XMen_lib_asn1_sm2_integer_to_der(r, 32, out, outlen);
        if (result != 1)
        {
            return -1;
        }
    
        result = XMen_lib_asn1_sm2_integer_to_der(s, 32, out, outlen);
        if (result != 1)
        {
            return -1;
        }
    
        return 1;
    }

    #include <string.h>  // 确保包含必要的头文件

    static int EasyXMen_SM2_Der2Sig(uint8 *r_sig, uint8 *s_sig, const uint8 **in, uint32 *inlen)
    {
        int ret;
        const uint8 *d = NULL;
        uint32 dlen = 0;
        const uint8 *r = NULL;
        uint32 rlen = 0;
        const uint8 *s = NULL;
        uint32 slen = 0;
    
        // Parse sequence header
        ret = XMen_lib_asn1_sm2_sequence_from_der(&d, &dlen, in, inlen);
        if (ret != 1)
        {
            if (ret < 0)
            {
                return ret;  // 保留原始错误码
            }
            return -1;       // 如果返回值不为1且不小于0，返回-1
        }
    
        // Parse signature components
        ret = XMen_lib_asn1_sm2_integer_from_der(&r, &rlen, &d, &dlen);
        if (ret != 1)
        {
            return -1;
        }
    
        ret = XMen_lib_asn1_sm2_integer_from_der(&s, &slen, &d, &dlen);
        if (ret != 1)
        {
            return -1;
        }
    
        ret = EasyXmen_SM2_Asn1_LenCmp(rlen, 32);
        if (ret != 1)
        {
            return -1;
        }
    
        ret = EasyXmen_SM2_Asn1_LenCmp(slen, 32);
        if (ret != 1)
        {
            return -1;
        }
    
        ret = EasyXmen_SM2_Asn1_LenIsZero(dlen);
        if (ret != 1)
        {
            return -1;
        }
    
        // Copy signature components to output structure
        // 确保 r_sig 和 s_sig 的大小足够，避免缓冲区溢出
        if (rlen > 32 || slen > 32)
        {
            return -1;  // 如果 rlen 或 slen 超过 32，返回错误
        }
    
        memcpy(r_sig + (32 - rlen), r, rlen);  // MISRA C:2012 Rule 17.4
        memcpy(s_sig + (32 - slen), s, slen);  // MISRA C:2012 Rule 17.4
    
        return 1;
    }

/**
 * @description Computes the SM3 hash for a given set of parameters including user ID, public key components (xa and ya), and a message.
 *        The function prepares a buffer with the provided data, computes an intermediate SM3 hash over this buffer,
 *        combines it with the message, and finally computes the SM3 hash over the combination.
 * @param[in] userid : Pointer to the user ID byte array.
 * @param[in] userid_len : Length of the user ID byte array in bytes.
 * @param[in] xa : Pointer to the X component of the public key byte array.
 * @param[in] xa_len : Length of the X component byte array in bytes. Must not exceed 32 bytes.
 * @param[in] ya : Pointer to the Y component of the public key byte array.
 * @param[in] ya_len : Length of the Y component byte array in bytes. Must not exceed 32 bytes.
 * @param[in] msg : Pointer to the message byte array to be hashed.
 * @param[in] msg_len : Length of the message byte array in bytes.
 * @param[out] e : Pointer to the output buffer where the resulting hash will be stored.
 * @return int
 * @retval 0 : Hash computation was successful.
 * @retval -1 : An error occurred, either due to invalid input lengths or memory allocation failure.
 */
int EasyXMen_sm3Hash(unsigned char *userid, int userid_len, unsigned char *xa, int xa_len, unsigned char *ya, int ya_len, unsigned char *msg, int msg_len, unsigned char *e)
{
    unsigned char buf[MAX_BUFFER_SIZE];  // 使用静态内存分配
    int userid_bitlen;

    // 检查输入参数的有效性
    if ((xa_len > 32) || (ya_len > 32) || (userid_len > MAX_USERID_LEN) || (msg_len > MAX_MSG_LEN))
        return -1;

    userid_bitlen = userid_len << 3;  // 计算 userid 的位长度
    buf[0] = (unsigned char)((userid_bitlen >> 8) & 0xFF);
    buf[1] = (unsigned char)(userid_bitlen & 0xFF);

    // 复制 userid 到缓冲区
    memcpy(buf + 2, userid, userid_len);

    // 复制固定参数（假设 sm2_par_dig 是一个全局变量或宏）
    memcpy(buf + 2 + userid_len, sm2_par_dig, 128);

    // 初始化剩余部分为 0
    memset(buf + 2 + userid_len + 128, 0, 64);

    // 复制 xa 和 ya 到缓冲区
    memcpy(buf + 2 + userid_len + 128 + 32 - xa_len, xa, xa_len);
    memcpy(buf + 2 + userid_len + 128 + 64 - ya_len, ya, ya_len);

    // 计算第一轮 SM3 哈希
    EasyXMen_sm3(buf, 2 + userid_len + 128 + 64, e);

    // 使用 e 和消息进行第二轮 SM3 哈希
    unsigned char msg_buf[MAX_MSG_LEN + 32];  // 使用静态内存分配
    memcpy(msg_buf, e, 32);
    memcpy(msg_buf + 32, msg, msg_len);

    EasyXMen_sm3(msg_buf, 32 + msg_len, e);

    return 0;
}

/**
 * @description Performs the SM2 digital signature generation on a given hash using the provided private key.
 *        The function initializes necessary elliptic curve parameters, generates a random number,
 *        and computes the signature (r, s) pair for the input hash value. It ensures that the generated
 *        values are valid and re-executes the signing process if invalid values are obtained.
 * @param[in]  hash      : Pointer to the hash byte array to be signed.
 * @param[in]  hashlen   : Length of the hash byte array in bytes.
 * @param[in]  privkey   : Pointer to the private key byte array.
 * @param[in]  privkeylen: Length of the private key byte array in bytes.
 * @param[out] cr        : Pointer to the output buffer where the 'r' component of the signature will be stored.
 * @param[out] rlen      : Pointer to an integer where the length of the 'r' component will be stored.
 * @param[out] cs        : Pointer to the output buffer where the 's' component of the signature will be stored.
 * @param[out] slen      : Pointer to an integer where the length of the 's' component will be stored.
 * @return void
 */
void EasyXMen_sm2_sign(unsigned char *hash, int hashlen, unsigned char *privkey, int privkeylen, unsigned char *cr, int *rlen, unsigned char *cs, int *slen)
{
    XMen_FP_EccT *cfig = &Ecc256;
    XMen_BigTPtr e, r, s, k;
    XMen_BigTPtr a, b, p, n, x, y, key1;
    XMen_ECurvePointT *g;
    XMen_SM2Type *mip = XMen_Mirsys(20, 0);

    mip->IOBASE = 16;

    // 初始化大数变量
    e = XMen_Mirvar(0);
    r = XMen_Mirvar(0);
    s = XMen_Mirvar(0);
    k = XMen_Mirvar(0);

    p = XMen_Mirvar(0);
    a = XMen_Mirvar(0);
    b = XMen_Mirvar(0);
    n = XMen_Mirvar(0);
    x = XMen_Mirvar(0);
    y = XMen_Mirvar(0);

    key1 = XMen_Mirvar(0);

    // 将私钥转换为大数
    XMen_Bytes2Big(privkeylen, (char *)privkey, key1);

    // 初始化椭圆曲线参数
    XMen_Cinstr(p, cfig->p);
    XMen_Cinstr(a, cfig->a);
    XMen_Cinstr(b, cfig->b);
    XMen_Cinstr(n, cfig->n);
    XMen_Cinstr(x, cfig->x);
    XMen_Cinstr(y, cfig->y);

    XMen_EcurveInit(a, b, p, XMEN_PROJECTIVE);
    g = XMen_EpointInit();
    XMen_EpointSet(x, y, 0, g);

    // 将哈希值转换为大数
    XMen_Bytes2Big(hashlen, (char *)hash, e);

    // 初始化随机数生成器
    XMen_Irand(time(NULL) + SEED_CONST);  // 注意：time(NULL) 的使用可能需要替换为更安全的方式

    // 签名循环
    while (1)
    {
        // 生成随机数 k
        XMen_BigRand(n, k);
        if (k->len == 0)
            continue;

        // 计算点 k * G
        XMen_EcurveMult(k, g, g);
        XMen_EpointGet(g, r, r);

        // 计算 r = (e + x1) mod n
        XMen_Add(e, r, r);
        XMen_Divide(r, n, n);

        if (r->len == 0)
            continue;

        // 计算 a = (r + k) mod n
        XMen_Add(r, k, a);
        if (XMen_Compare(a, n) == 0)
            continue;

        // 计算 b = key1^(-1) mod n
        XMen_Incr(key1, 1, b);
        XMen_Xgcd(b, n, b, b, b);

        // 计算 s = (a * key1^(-1)) mod n
        XMen_Multiply(r, key1, a);
        XMen_Divide(a, n, n);

        if (XMen_Compare(k, a) >= 0)
        {
            XMen_Subtract(k, a, a);
        }
        else
        {
            XMen_Subtract(n, a, a);
            XMen_Add(k, a, a);
        }

        XMen_Mad(a, b, a, n, n, s);

        if (s->len == 0)
            continue;

        // 成功生成签名
        break;
    }

    // 将大数转换为字节数组
    *rlen = XMen_Big2Bytes(0, r, (char *)cr, FALSE);
    *slen = XMen_Big2Bytes(0, s, (char *)cs, FALSE);

    // 清理资源
    XMen_Mirkill(e);
    XMen_Mirkill(r);
    XMen_Mirkill(s);
    XMen_Mirkill(k);
    XMen_Mirkill(p);
    XMen_Mirkill(a);
    XMen_Mirkill(b);
    XMen_Mirkill(n);
    XMen_Mirkill(x);
    XMen_Mirkill(y);
    XMen_Mirkill(key1);
    XMen_EpointFree(g);
    XMen_Mirexit();
}

/**
 * @description Verifies the SM2 digital signature for a given hash using the provided public key components and signature values.
 *        The function checks if the signature (r, s) pair is valid for the input hash value based on the specified elliptic curve parameters.
 *        It ensures that all intermediate values are within expected bounds and performs necessary computations to validate the signature.
 * @param[in]  hash   : Pointer to the hash byte array that was signed.
 * @param[in]  hashlen: Length of the hash byte array in bytes.
 * @param[in]  cr     : Pointer to the 'r' component of the signature byte array.
 * @param[in]  rlen   : Length of the 'r' component byte array in bytes.
 * @param[in]  cs     : Pointer to the 's' component of the signature byte array.
 * @param[in]  slen   : Length of the 's' component byte array in bytes.
 * @param[in]  wx     : Pointer to the X component of the public key byte array.
 * @param[in]  wxlen  : Length of the X component byte array in bytes.
 * @param[in]  wy     : Pointer to the Y component of the public key byte array.
 * @param[in]  wylen  : Length of the Y component byte array in bytes.
 * @return int
 * @retval 0 : The signature is valid for the given hash and public key.
 * @retval -1: The signature verification failed or an error occurred.

 */
int EasyXMen_sm2_verify(unsigned char *hash, int hashlen, unsigned char *cr, int rlen, unsigned char *cs, int slen, unsigned char *wx, int wxlen, unsigned char *wy, int wylen)
{
    XMen_FP_EccT *cfig = &Ecc256;
    XMen_BigTPtr e, r, s, v;
    XMen_BigTPtr a, b, p, n, x, y;
    XMen_ECurvePointT *g, *w;
    int ret = -1;
    XMen_SM2Type *mip = XMen_Mirsys(20, 0);

    mip->IOBASE = 16;

    p = XMen_Mirvar(0);
    a = XMen_Mirvar(0);
    b = XMen_Mirvar(0);
    n = XMen_Mirvar(0);
    x = XMen_Mirvar(0);
    y = XMen_Mirvar(0);

    e = XMen_Mirvar(0);
    r = XMen_Mirvar(0);
    s = XMen_Mirvar(0);
    v = XMen_Mirvar(0);

    XMen_Cinstr(p, cfig->p);
    XMen_Cinstr(a, cfig->a);
    XMen_Cinstr(b, cfig->b);
    XMen_Cinstr(n, cfig->n);
    XMen_Cinstr(x, cfig->x);
    XMen_Cinstr(y, cfig->y);

    XMen_EcurveInit(a, b, p, XMEN_PROJECTIVE);
    g = XMen_EpointInit();
    w = XMen_EpointInit();
    XMen_EpointSet(x, y, 0, g);

    XMen_Bytes2Big(wxlen, (char *)wx, x);
    XMen_Bytes2Big(wylen, (char *)wy, y);

    if (!XMen_EpointSet(x, y, 0, w))
    {
        ret = -1;
        goto cleanup;
    }

    XMen_Bytes2Big(hashlen, (char *)hash, e);
    XMen_Bytes2Big(rlen, (char *)cr, r);
    XMen_Bytes2Big(slen, (char *)cs, s);

    if ((XMen_Compare(r, n) >= 0) || (r->len == 0))
    {
        ret = -1;
        goto cleanup;
    }

    if ((XMen_Compare(s, n) >= 0) || (s->len == 0))
    {
        ret = -1;
        goto cleanup;
    }

    XMen_Add(s, r, a);
    XMen_Divide(a, n, n);

    if (a->len == 0)
    {
        ret = -1;
        goto cleanup;
    }

    XMen_EcurveMult2(s, g, a, w, g);
    XMen_EpointGet(g, v, v);

    XMen_Add(v, e, v);
    XMen_Divide(v, n, n);

    if (XMen_Compare(v, r) == 0)
    {
        ret = 0;
    }

cleanup:
    XMen_Mirkill(r);
    XMen_Mirkill(s);
    XMen_Mirkill(v);
    XMen_Mirkill(e);
    XMen_Mirkill(a);
    XMen_Mirkill(b);
    XMen_Mirkill(p);
    XMen_Mirkill(n);
    XMen_Mirkill(x);
    XMen_Mirkill(y);
    XMen_EpointFree(g);
    XMen_EpointFree(w);
    XMen_Mirexit();

    return ret;
}

BOOL XMen_point_at_infinity(XMen_ECurvePointT *p)
{
    if (p == NULL)
        return FALSE;
    if (p->marker == XMEN_EPOINT_INFINITY)
        return TRUE;
    return FALSE;
}
int XMen_kdf(unsigned char *zl, unsigned char *zr, int klen, unsigned char *kbuf)
{
    unsigned char buf[BUF_SIZE];
    unsigned char digest[SM3_DIGEST_SIZE];
    unsigned int ct = 0x00000001;
    int i, m, n;
    unsigned char *p;

    // 检查输入参数的有效性
    if ((zl == NULL) || (zr == NULL) || (kbuf == NULL) || (klen <= 0) || (klen > MAX_KBUF_SIZE))
    {
        return 0;  // 输入无效，返回 0
    }

    // 初始化 buf
    memcpy(buf, zl, SM3_DIGEST_SIZE);
    memcpy(buf + SM3_DIGEST_SIZE, zr, SM3_DIGEST_SIZE);

    m = klen / SM3_DIGEST_SIZE;
    n = klen % SM3_DIGEST_SIZE;
    p = kbuf;

    for (i = 0; i < m; i++)
    {
        buf[SM3_DIGEST_SIZE * 2] = (ct >> 24) & 0xFF;
        buf[SM3_DIGEST_SIZE * 2 + 1] = (ct >> 16) & 0xFF;
        buf[SM3_DIGEST_SIZE * 2 + 2] = (ct >> 8) & 0xFF;
        buf[SM3_DIGEST_SIZE * 2 + 3] = ct & 0xFF;

        EasyXMen_sm3(buf, BUF_SIZE, p);  // 计算 SM3 摘要
        p += SM3_DIGEST_SIZE;
        ct++;
    }

    if (n != 0)
    {
        buf[SM3_DIGEST_SIZE * 2] = (ct >> 24) & 0xFF;
        buf[SM3_DIGEST_SIZE * 2 + 1] = (ct >> 16) & 0xFF;
        buf[SM3_DIGEST_SIZE * 2 + 2] = (ct >> 8) & 0xFF;
        buf[SM3_DIGEST_SIZE * 2 + 3] = ct & 0xFF;

        EasyXMen_sm3(buf, BUF_SIZE, digest);  // 计算 SM3 摘要
        memcpy(p, digest, n);  // 复制剩余部分
    }

    // 检查 kbuf 是否全为 0
    for (i = 0; i < klen; i++)
    {
        if (kbuf[i] != 0)
        {
            return 1;  // kbuf 不全为 0，返回 1
        }
    }

    return 0;  // kbuf 全为 0，返回 0
}

int EasyXMen_sm2_encrypt(unsigned char *msg, int msglen, unsigned char *wx, int wxlen, unsigned char *wy, int wylen, unsigned char *outmsg, int *outlen)
{
    XMen_FP_EccT *cfig = &Ecc256;
    XMen_BigTPtr x2, y2, x1, y1, k;
    XMen_BigTPtr a, b, p, n, x, y;
    XMen_ECurvePointT *g, *w;
    int ret = -1;
    int i;
    unsigned char zl[32], zr[32];
    unsigned char temp1[MAX_MSG_LEN];
    unsigned char tmp[MAX_MSG_LEN + 64];
    XMen_SM2Type *mip;

    // 输入参数检查
    if ((msg == NULL) || (wx == NULL) || (wy == NULL) || (outmsg == NULL) || (outlen == NULL) || (msglen > MAX_MSG_LEN))
    {
        return -1;
    }

    mip = XMen_Mirsys(20, 0);
    mip->IOBASE = 16;

    p = XMen_Mirvar(0);
    a = XMen_Mirvar(0);
    b = XMen_Mirvar(0);
    n = XMen_Mirvar(0);
    x = XMen_Mirvar(0);
    y = XMen_Mirvar(0);

    k = XMen_Mirvar(0);
    x2 = XMen_Mirvar(0);
    y2 = XMen_Mirvar(0);
    x1 = XMen_Mirvar(0);
    y1 = XMen_Mirvar(0);

    XMen_Cinstr(p, cfig->p);
    XMen_Cinstr(a, cfig->a);
    XMen_Cinstr(b, cfig->b);
    XMen_Cinstr(n, cfig->n);
    XMen_Cinstr(x, cfig->x);
    XMen_Cinstr(y, cfig->y);

    XMen_EcurveInit(a, b, p, XMEN_PROJECTIVE);
    g = XMen_EpointInit();
    w = XMen_EpointInit();
    XMen_EpointSet(x, y, 0, g);
    XMen_Bytes2Big(wxlen, (char *)wx, x);
    XMen_Bytes2Big(wylen, (char *)wy, y);
    XMen_EpointSet(x, y, 0, w);

    XMen_Irand(time(NULL) + SEED_CONST);

    // 加密循环
    while (1)
    {
        // 生成随机数 k
        do
        {
            XMen_BigRand(n, k);
        } while (k->len == 0);

        // 计算点 k * G
        XMen_EcurveMult(k, g, g);
        XMen_EpointGet(g, x1, y1);
        XMen_Big2Bytes(32, x1, (char *)outmsg, TRUE);
        XMen_Big2Bytes(32, y1, (char *)outmsg + 32, TRUE);

        // 计算点 k * W
        XMen_EcurveMult(k, w, w);
        XMen_EpointGet(w, x2, y2);

        XMen_Big2Bytes(32, x2, (char *)zl, TRUE);
        XMen_Big2Bytes(32, y2, (char *)zr, TRUE);

        // 使用 KDF 生成密钥
        if (XMen_kdf(zl, zr, msglen, outmsg + 96) == 0)
        {
            continue;  // 如果 KDF 失败，重新生成 k
        }

        // 加密消息
        for (i = 0; i < msglen; i++)
        {
            temp1[i] = msg[i] ^ outmsg[96 + i];
        }

        // 计算摘要
        memcpy(tmp, zl, 32);
        memcpy(tmp + 32, temp1, msglen);
        memcpy(tmp + 32 + msglen, zr, 32);

        EasyXMen_sm3(tmp, 64 + msglen, &outmsg[64]);
        memcpy(outmsg + 64 + 32, temp1, msglen);

        *outlen = msglen + 64 + 32;
        ret = 0;
        break;
    }

    // 清理资源
    XMen_Mirkill(x2);
    XMen_Mirkill(y2);
    XMen_Mirkill(x1);
    XMen_Mirkill(y1);
    XMen_Mirkill(k);
    XMen_Mirkill(a);
    XMen_Mirkill(b);
    XMen_Mirkill(p);
    XMen_Mirkill(n);
    XMen_Mirkill(x);
    XMen_Mirkill(y);
    XMen_EpointFree(g);
    XMen_EpointFree(w);
    XMen_Mirexit();

    return ret;
}
int EasyXMen_sm2_decrypt(unsigned char *msg, int msglen, unsigned char *privkey, int privkeylen, unsigned char *outmsg, int *outlen)
{
    XMen_FP_EccT *cfig = &Ecc256;
    XMen_BigTPtr x2, y2, c, k;
    XMen_BigTPtr a, b, p, n, x, y, key1;
    XMen_ECurvePointT *g;

    unsigned char c3[SM3_DIGEST_SIZE];
    unsigned char zl[SM3_DIGEST_SIZE], zr[SM3_DIGEST_SIZE];
    int i, ret = -1;
    unsigned char tmp[MAX_MSG_LEN + 64];  // 使用静态数组替代动态分配

    XMen_SM2Type *mip;

    // 输入参数检查
    if ((msg == NULL) || (privkey == NULL) || (outmsg == NULL) || (outlen == NULL) || (msglen < 96) || (msglen > MAX_MSG_LEN))
    {
        return -1;
    }

    mip = XMen_Mirsys(20, 0);
    mip->IOBASE = 16;

    x2 = XMen_Mirvar(0);
    y2 = XMen_Mirvar(0);
    c = XMen_Mirvar(0);
    k = XMen_Mirvar(0);

    p = XMen_Mirvar(0);
    a = XMen_Mirvar(0);
    b = XMen_Mirvar(0);
    n = XMen_Mirvar(0);
    x = XMen_Mirvar(0);
    y = XMen_Mirvar(0);
    key1 = XMen_Mirvar(0);

    XMen_Bytes2Big(privkeylen, (char *)privkey, key1);
    XMen_Cinstr(p, cfig->p);
    XMen_Cinstr(a, cfig->a);
    XMen_Cinstr(b, cfig->b);
    XMen_Cinstr(n, cfig->n);
    XMen_Cinstr(x, cfig->x);
    XMen_Cinstr(y, cfig->y);
    XMen_EcurveInit(a, b, p, XMEN_PROJECTIVE);
    g = XMen_EpointInit();

    XMen_Bytes2Big(SM3_DIGEST_SIZE, (char *)msg, x);
    XMen_Bytes2Big(SM3_DIGEST_SIZE, (char *)msg + SM3_DIGEST_SIZE, y);
    if (!XMen_EpointSet(x, y, 0, g))
    {
        ret = -1;
        goto cleanup;
    }

    if (XMen_point_at_infinity(g))
    {
        ret = -1;
        goto cleanup;
    }

    XMen_EcurveMult(key1, g, g);
    XMen_EpointGet(g, x2, y2);

    XMen_Big2Bytes(SM3_DIGEST_SIZE, x2, (char *)zl, TRUE);
    XMen_Big2Bytes(SM3_DIGEST_SIZE, y2, (char *)zr, TRUE);

    if (XMen_kdf(zl, zr, msglen - 96, outmsg) == 0)
    {
        ret = -1;
        goto cleanup;
    }

    for (i = 0; i < msglen - 96; i++)
    {
        outmsg[i] ^= msg[i + 64 + SM3_DIGEST_SIZE];
    }

    memcpy(tmp, zl, SM3_DIGEST_SIZE);
    memcpy(tmp + SM3_DIGEST_SIZE, outmsg, msglen - 96);
    memcpy(tmp + SM3_DIGEST_SIZE + (msglen - 96), zr, SM3_DIGEST_SIZE);

    EasyXMen_sm3(tmp, 64 + (msglen - 96), c3);

    if (memcmp(c3, msg + 64, SM3_DIGEST_SIZE) != 0)
    {
        ret = -1;
        goto cleanup;
    }

    *outlen = msglen - 96;
    ret = 0;

cleanup:
    XMen_Mirkill(x2);
    XMen_Mirkill(y2);
    XMen_Mirkill(c);
    XMen_Mirkill(k);
    XMen_Mirkill(p);
    XMen_Mirkill(a);
    XMen_Mirkill(b);
    XMen_Mirkill(n);
    XMen_Mirkill(x);
    XMen_Mirkill(y);
    XMen_Mirkill(key1);
    XMen_EpointFree(g);
    XMen_Mirexit();

    return ret;
}

void Crypto_SM2_signProcess()
{

    unsigned char userid[] = "1234567812345678";
    int userid_len = sizeof(userid) - 1;

    /*Declare two unsigned char arrays named r_sm2 and s_sm2 that will be used to
     *store the R and S values obtained during the signing process.*/
    unsigned char r_sm2[32];
    unsigned char s_sm2[32];
    int rlen, slen;

    unsigned char kA_sm2[32];
    uint32 kA_sm2_len = 32;

    unsigned char xa[32];
    uint32 xa_len = sizeof(xa);

    unsigned char ya[32];
    uint32 ya_len = sizeof(ya);

    unsigned char e[32];

    /*Input Data.*/
    uint32 ilen = Crypto_StoredJob.jobPrimitiveInputOutput.inputLength;
    uint8 *input = (uint8 *)(Crypto_StoredJob.jobPrimitiveInputOutput.inputPtr);
    uint8 *output = (uint8 *)(Crypto_StoredJob.jobPrimitiveInputOutput.outputPtr);

    Crypto_KeyElementGet(0, 1, kA_sm2, &kA_sm2_len);
    Crypto_KeyElementGet(1, 1, xa, &xa_len);
    Crypto_KeyElementGet(2, 3, ya, &ya_len);

    EasyXMen_sm3Hash(userid, userid_len, xa, xa_len, ya, ya_len, input, ilen, e);
    EasyXMen_sm2_sign(e, 32, kA_sm2, 32, r_sm2, &rlen, s_sm2, &slen);
    uint32 *siglen = (Crypto_StoredJob.jobPrimitiveInputOutput.outputLengthPtr);
    EasyXMen_SM2_Sig2Der(r_sm2, s_sm2, &output, siglen);
}

void Crypto_SM2_verifyProcess()
{
    int ret;
    unsigned char userid[] = "1234567812345678";
    int userid_len = sizeof(userid) - 1;

    /*Declare two unsigned char arrays named r_sm2 and s_sm2 that will be used to
     *store the R and S values obtained during the signing process.*/
    unsigned char r_sm2[32];
    unsigned char s_sm2[32];

    unsigned char kA_sm2[32];
    uint32 kA_sm2_len = 32;

    unsigned char xa[32];
    uint32 xa_len = sizeof(xa);

    unsigned char ya[32];
    uint32 ya_len = sizeof(ya);

    unsigned char e[32];

    uint32 ilen = Crypto_StoredJob.jobPrimitiveInputOutput.inputLength;
    const uint8 *input = (uint8 *)(Crypto_StoredJob.jobPrimitiveInputOutput.inputPtr);
    const uint8 *sig_result = Crypto_StoredJob.jobPrimitiveInputOutput.secondaryInputPtr;
    uint32 siglen = Crypto_StoredJob.jobPrimitiveInputOutput.secondaryInputLength;

    memset(r_sm2, 0, 32);
    memset(s_sm2, 0, 32);
    EasyXMen_SM2_Der2Sig(r_sm2, s_sm2, &sig_result, &siglen);

    Crypto_KeyElementGet(0, 1, kA_sm2, &kA_sm2_len);
    Crypto_KeyElementGet(1, 1, xa, &xa_len);
    Crypto_KeyElementGet(2, 3, ya, &ya_len);

    EasyXMen_sm3Hash(userid, userid_len, xa, xa_len, ya, ya_len, input, ilen, e);

    ret = EasyXMen_sm2_verify(e, 32, r_sm2, 32, s_sm2, 32, xa, 32, ya, 32);
    if (ret == 0)
    {
        *Crypto_StoredJob.jobPrimitiveInputOutput.verifyPtr = 0;
    }
    else
    {
        *Crypto_StoredJob.jobPrimitiveInputOutput.verifyPtr = 1;
    }
}

void Crypto_SM2_encryProcess()
{
    int etx_len;
    unsigned char kA_sm2[32];
    uint32 kA_sm2_len = 32;

    unsigned char xa[32];
    uint32 xa_len = sizeof(xa);

    unsigned char ya[32];
    uint32 ya_len = sizeof(ya);

    uint32 ilen = Crypto_StoredJob.jobPrimitiveInputOutput.inputLength;
    const uint8 *input = (uint8 *)(Crypto_StoredJob.jobPrimitiveInputOutput.inputPtr);

    Crypto_KeyElementGet(0, 1, kA_sm2, &kA_sm2_len);
    Crypto_KeyElementGet(1, 1, xa, &xa_len);
    Crypto_KeyElementGet(2, 3, ya, &ya_len);

    unsigned char *etx = (unsigned char *)malloc((ilen + 96) * sizeof(unsigned char));

    EasyXMen_sm2_encrypt(input, ilen, xa, xa_len, ya, ya_len, etx, &etx_len);

    for (int i = 0; i < etx_len; i++)
    {
        Crypto_StoredJob.jobPrimitiveInputOutput.outputPtr[i] = etx[i];
    }
    *Crypto_StoredJob.jobPrimitiveInputOutput.outputLengthPtr = etx_len;
}

void Crypto_SM2_decryProcess()
{
    int mtx_len;
    unsigned char kA_sm2[32];
    uint32 kA_sm2_len = 32;

    uint32 ilen = Crypto_StoredJob.jobPrimitiveInputOutput.inputLength;
    const uint8 *input = (uint8 *)(Crypto_StoredJob.jobPrimitiveInputOutput.inputPtr);

    unsigned char *mtx = (unsigned char *)malloc(ilen * sizeof(unsigned char));

    Crypto_KeyElementGet(0, 1, kA_sm2, &kA_sm2_len);

    EasyXMen_sm2_decrypt(input, ilen, kA_sm2, kA_sm2_len, mtx, &mtx_len);

    for (int i = 0; i < mtx_len; i++)
    {
        Crypto_StoredJob.jobPrimitiveInputOutput.outputPtr[i] = mtx[i];
    }
    *Crypto_StoredJob.jobPrimitiveInputOutput.outputLengthPtr = mtx_len;
}
